object Combiner extends Application {
	
	def combine(strokes: Int, maxStroke: Int): Iterator[List[(Int, Int)]] =
		if (strokes == 0)
			List(List()).iterator
		else if (maxStroke == 0 || strokes < 0)
			Iterator()
		else
			{(Iterator[List[(Int, Int)]]() /:
				{ for (i <- 1 to (strokes / maxStroke) reverse)
					yield for (combined <- combine(strokes - i * maxStroke, maxStroke - 1))
						yield List((maxStroke, i)) ++ combined
				}
			) {_ ++ _}} ++ {
				for (c <- combine(strokes, maxStroke - 1))
					yield c
			}
			
	def shuffle(pairs: Array[(Int, Int)]): Iterator[List[Int]] = {
		val iterator = (Iterator[List[Int]]() /: {
			for (i <- 0 until pairs.length)
				yield {
					val (strokes, count) = pairs(i)
					if (count > 0) {
						pairs(i) = (strokes, count - 1)
						val shuffledIterator = for (shuffled <- shuffle(pairs))
							yield List(strokes) ++ shuffled
						pairs(i) = (strokes, count)
						shuffledIterator
					} else {
						Iterator()
					}
				}
		}) {_ ++ _}
		if (iterator.hasNext)
			iterator
		else
			Iterator(List())
	}

	def letterize(shuffles: List[Int], letters: List[String], charFilter: (Char, Char) => Boolean): Iterator[String] = {
		if (shuffles == List())
			Iterator("")
		else {
			var iterator = Iterator[String]()
			for (key <- shuffles)
				for (stroke <- letters(key - 1))
					if (stroke != ' ')
						iterator ++= {
							for (letterized <- letterize(shuffles.tail, letters, charFilter) if letterized.length == 0 || charFilter(stroke, letterized(0)))
								yield stroke + letterized
						}
			iterator
		}
	}

	def mapKeys(letters: List[String]): Map[Char, Int] = {
		val keys = scala.collection.mutable.Map[Char, Int]()
		for (keyLetters <- letters; key <- 0 until keyLetters.length)
			keys.put(keyLetters(key), key)
		Map() ++ keys
	}

	val enLetters = List(
		"adgjmptw",
		"behknqux",
		"cfilorvy",
		"23456s8z",
		"     7 9"
	)

	val letters = enLetters

	val keys = mapKeys(letters)

	for(combined <- combine(4, letters.length)) {
		println("Combined: " + combined);
		for (shuffled <- shuffle(combined.toArray)){
			println("Shuffled: " + shuffled)
			for (letterized <- letterize(shuffled, letters, (char1: Char, char2: Char) =>  {keys(char1) != keys(char2)}))
				println ("Letterized: " + letterized)
		}
	}

}